﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GCTrackableRace.Interfaces;
using log4net;
using System.IO;

namespace GcTrackableRace.Persistence
{
	public class ScoreCsvFilePersistence: IScorePersistance
	{
		public ScoreCsvFilePersistence(ILog log)
		{
			Log = log;
		}

		public void PersistTrackableScores(IEnumerable<ITrackable> trackables, IProgramConfigurationSettings programConfigurationSettings)
		{
			var csvText = GenerateCsvText(trackables);

			PersistCsvText(csvText, programConfigurationSettings);
		}

		private ILog Log { get; set; }

		#region Private Methods

		private static string GenerateCsvText(IEnumerable<ITrackable> trackables)
		{
			var sb = new StringBuilder();

			sb.AppendLine(CreatedCsvHeaders(trackables.First()));

			foreach (var trackable in trackables.OrderBy(t => t.Name))
			{
				var scoreDetials = GetScoreDetails(trackable);

				sb.AppendLine(String.Format("{0},{1},{2},{3},{4},{5},{6},{7}",
					trackable.Name,
					trackable.Code, 
					trackable.Owner, 
					trackable.Country, 
					trackable.State, 
					trackable.County, 
					trackable.TrackableType,
					scoreDetials));
			}

			return sb.ToString();
		}

		private static void PersistCsvText(string csvText, IProgramConfigurationSettings programConfigurationSettings)
		{
			var fileNameAndPath = programConfigurationSettings.GetOutputFileNameAndLocation(FileType.CsvRaceResultTextFile);

			if (File.Exists(fileNameAndPath))
				File.Delete(fileNameAndPath);

			if (!Directory.Exists(programConfigurationSettings.OutputDirectory))
				Directory.CreateDirectory(programConfigurationSettings.OutputDirectory);

			File.WriteAllText(fileNameAndPath, csvText);
		}

		private static string CreatedCsvHeaders(ITrackable trackable)
		{
			var sb = new StringBuilder();

			sb.Append("Name,Code,Owner,From-Country,From-State,From-County,TrackableType,");

			foreach (var ruleScore in trackable.RuleScores)
			{
				sb.Append(String.Format("{0}-Count,{0}-Score,{0}-Detail,", ruleScore.ReportColumnName));
			}

			return sb.ToString();
		}

		private static object GetScoreDetails(ITrackable trackable)
		{
			var sb = new StringBuilder();

			foreach (var ruleScore in trackable.RuleScores)
			{
				sb.Append(String.Format("{0},{1},{2}", ruleScore.Count,ruleScore.Score, ruleScore.ScoreDetails));
			}

			return sb.ToString();
		}
		
		#endregion Private Methods
	}
}
